﻿using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Yyd.Security.Claims;

namespace Yyd.Security.Permissions
{
    public class CurrentPermission : ICurrentPermission, ITransientDependency
    {
        private readonly ICurrentPrincipalAccessor _principalAccessor;

        private readonly ICurrentPermissionAccessor _userPermissionAccessor;

        public CurrentPermission(ICurrentPrincipalAccessor principalAccessor,
            ICurrentPermissionAccessor userPermissionAccessor)
        {
            _principalAccessor = principalAccessor;
            _userPermissionAccessor = userPermissionAccessor;
        }

        public Guid? UserId => _userPermissionAccessor.Current != null
            ? _userPermissionAccessor.Current.UserId
            : _principalAccessor.Principal?.FindUserId();

        public string Name => _userPermissionAccessor.Current != null
            ? _userPermissionAccessor.Current.Name
            : FindClaimValue(YydClaimTypes.Permission);

        public IDisposable Change(string name = null)
        {
            var parentScope = _userPermissionAccessor.Current;
            _userPermissionAccessor.Current = new PermissionInfo(UserId, name);

            return new DisposeAction(() => { _userPermissionAccessor.Current = parentScope; });
        }

        protected virtual Claim FindClaim(string claimType)
        {
            return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType && !c.Value.IsNullOrWhiteSpace());
        }

        protected virtual string FindClaimValue(string claimType)
        {
            return FindClaim(claimType)?.Value;
        }
    }
}
